#include "TesselCube.h"

#include <gl\glfw.h>
#include <math.h>

	float lerp( float x1, float x2, float t)
	{
		return x1 + (x2-x1)*t;
	}

	void TesselCube::init()
		{
			segs = 20;
			//indices = new std::vector< std::vector<GLint> >(6*(segs-1)*(segs-1), std::vector<GLint>(4,0));

			indices.resize( 6*(segs-1)*(segs-1) );
			for(size_t i=0; i< indices.size(); i++)
			{
				indices[i].resize(4);
			}
			vertices.resize(6*segs*segs);
			normals.resize(6*segs*segs);
			ballVerts.resize(6*segs*segs);
			ballNormals.resize(6*segs*segs);

			float scale = 1.5f;
			int idx = 0;
			float fsegs = segs - 1.0f;
			printf("\n");
			for(int i = 0; i<segs; i++)
			{
				for(int j = 0; j<segs; j++)
				{
					// +-Z
					vertices[idx].setXYZ( scale * (1-2*(float)i/fsegs), scale*(1-2*(float)j/fsegs), scale );   idx++;
					vertices[idx].setXYZ( scale * (1-2*(float)i/fsegs), scale*(1-2*(float)j/fsegs), -scale );  idx++;
					// +-Y
					vertices[idx].setXYZ( scale * (1-2*(float)i/fsegs), scale, scale*(1-2*(float)j/fsegs) );      idx++;
					vertices[idx].setXYZ( scale * (1-2*(float)i/fsegs), -scale, scale*(1-2*(float)j/fsegs) );     idx++;
					// +-X
					vertices[idx].setXYZ( scale , scale*(1-2*(float)j/fsegs),  scale*(1-2*(float)i/fsegs) );      idx++;
					vertices[idx].setXYZ( -scale , scale*(1-2*(float)j/fsegs),  scale*(1-2*(float)i/fsegs) );     idx++;


				}
			}

			// Bleh. got this by trial and error >.<
			idx = 0;
			for(int side=0; side<6; side++)
				for(int i = 1; i<segs; i++)
				{
					for(int j = 1; j<segs; j++)
					{
						if(side == 0 || side==5 || side==3)
						{
							indices[idx][3] = (i-1)*segs*6+(j-1)*6+side ;
							indices[idx][2] = (i-1)*segs*6+(j+0)*6+side ;
							indices[idx][1] = (i+0)*segs*6+(j+0)*6+side ;
							indices[idx][0] = (i+0)*segs*6+(j-1)*6+side ;

						}else{
							indices[idx][0] = (i-1)*segs*6+(j-1)*6+side ;
							indices[idx][1] = (i-1)*segs*6+(j+0)*6+side ;
							indices[idx][2] = (i+0)*segs*6+(j+0)*6+side ;
							indices[idx][3] = (i+0)*segs*6+(j-1)*6+side ;
						}
						idx++;
					}
				}

				// Now. make ball
				for(size_t i=0; i<vertices.size(); i++)
				{
					GLfloat nx = vertices[i].x;
					GLfloat ny = vertices[i].y;
					GLfloat nz = vertices[i].z;
					float len = sqrt( nx*nx + ny*ny + nz*nz );
					nx = nx/len;
					ny = ny/len;
					nz = nz/len;
					ballVerts[i].setXYZ(nx,ny,nz);
					ballNormals[i].setXYZ(nx - 0, ny - 0, nz - 0); // vec from center to surf
				}

		}

	void TesselCube::drawSphere()
		{
			int idx = 0;
			glBegin(GL_QUADS);
			for(int side=0; side<6; side++)
			{
				//vert norm;
				//vert color;
				//if(side==0) norm.setXYZ(0.0, 0.0, 1.0);
				//if(side==1) norm.setXYZ(0.0, 0.0,-1.0);
				//if(side==2) norm.setXYZ(0.0, 1.0, 0.0);
				//if(side==3) norm.setXYZ(0.0,-1.0, 0.0);
				//if(side==4) norm.setXYZ(1.0, 0.0, 0.0);
				//if(side==5) norm.setXYZ(-1.0, 0.0, 0.0);

				//if(side==0) color.setXYZ(1.0, 0.0, 0.0 );
				//if(side==1) color.setXYZ(0.0, 1.0, 0.0 );
				//if(side==2) color.setXYZ(0.0, 0.0, 1.0 );
				//if(side==3) color.setXYZ(1.0, 1.0, 0.0 );
				//if(side==4) color.setXYZ(0.0, 1.0, 1.0 );
				//if(side==5) color.setXYZ(1.0, 0.0, 1.0 );

				//glColor3f( color.x, color.y, color.z );
				//glNormal3f( norm.x, norm.y, norm.z );

				for(int i=0; i<(segs-1)*(segs-1); i++)
				{
					glNormal3f( ballNormals[ indices[idx][0] ].x, ballNormals[ indices[idx][0] ].y, ballNormals[ indices[idx][0] ].z );
					glVertex3f( ballVerts[ indices[idx][0] ].x, ballVerts[ indices[idx][0] ].y, ballVerts[ indices[idx][0] ].z );

					glNormal3f( ballNormals[ indices[idx][1] ].x, ballNormals[ indices[idx][1] ].y, ballNormals[ indices[idx][1] ].z );
					glVertex3f( ballVerts[ indices[idx][1] ].x, ballVerts[ indices[idx][1] ].y, ballVerts[ indices[idx][1] ].z );

					glNormal3f( ballNormals[ indices[idx][2] ].x, ballNormals[ indices[idx][2] ].y, ballNormals[ indices[idx][2] ].z );
					glVertex3f( ballVerts[ indices[idx][2] ].x, ballVerts[ indices[idx][2] ].y, ballVerts[ indices[idx][2] ].z );

					glNormal3f( ballNormals[ indices[idx][3] ].x, ballNormals[ indices[idx][3] ].y, ballNormals[ indices[idx][3] ].z );
					glVertex3f( ballVerts[ indices[idx][3] ].x, ballVerts[ indices[idx][3] ].y, ballVerts[ indices[idx][3] ].z );
					idx++;
				}
			}
			glEnd();

			glPopMatrix();

		}
	void TesselCube::drawCube()
	{
		int idx = 0;
		glBegin(GL_QUADS);
		for(int side=0; side<6; side++)
		{
			vert norm;
			vert color;
			if(side==0) norm.setXYZ(0.0, 0.0, 1.0);
			if(side==1) norm.setXYZ(0.0, 0.0,-1.0);
			if(side==2) norm.setXYZ(0.0, 1.0, 0.0);
			if(side==3) norm.setXYZ(0.0,-1.0, 0.0);
			if(side==4) norm.setXYZ(1.0, 0.0, 0.0);
			if(side==5) norm.setXYZ(-1.0, 0.0, 0.0);

			if(side==0) color.setXYZ(1.0, 0.0, 0.0 );
			if(side==1) color.setXYZ(0.0, 1.0, 0.0 );
			if(side==2) color.setXYZ(0.0, 0.0, 1.0 );
			if(side==3) color.setXYZ(1.0, 1.0, 0.0 );
			if(side==4) color.setXYZ(0.0, 1.0, 1.0 );
			if(side==5) color.setXYZ(1.0, 0.0, 1.0 );

			glColor3f( color.x, color.y, color.z );
			glNormal3f( norm.x, norm.y, norm.z );

			for(int i=0; i<(segs-1)*(segs-1); i++)
			{
				glVertex3f( vertices[ indices[idx][0] ].x, vertices[ indices[idx][0] ].y, vertices[ indices[idx][0] ].z );
				glVertex3f( vertices[ indices[idx][1] ].x, vertices[ indices[idx][1] ].y, vertices[ indices[idx][1] ].z );
				glVertex3f( vertices[ indices[idx][2] ].x, vertices[ indices[idx][2] ].y, vertices[ indices[idx][2] ].z );
				glVertex3f( vertices[ indices[idx][3] ].x, vertices[ indices[idx][3] ].y, vertices[ indices[idx][3] ].z );

				idx++;
			}
		}
		glEnd();
	}

	// This is REALLY! expensive! do it on gpu!
	void TesselCube::morph(float t)
	{
		int idx = 0;
		glBegin(GL_QUADS);
		for(int side=0; side<6; side++)
		{
			vert norm;
			vert color;
			if(side==0) norm.setXYZ(0.0, 0.0, 1.0);
			if(side==1) norm.setXYZ(0.0, 0.0,-1.0);
			if(side==2) norm.setXYZ(0.0, 1.0, 0.0);
			if(side==3) norm.setXYZ(0.0,-1.0, 0.0);
			if(side==4) norm.setXYZ(1.0, 0.0, 0.0);
			if(side==5) norm.setXYZ(-1.0, 0.0, 0.0);

			for(int i=0; i<(segs-1)*(segs-1); i++)
			{
				for(int j=0; j<4; j++)
				{
					GLfloat nx = lerp( norm.x, ballNormals[ indices[idx][j] ].x,t );
					GLfloat ny = lerp( norm.y, ballNormals[ indices[idx][j] ].y,t );
					GLfloat nz = lerp( norm.z, ballNormals[ indices[idx][j] ].z,t );

					GLfloat x = lerp( vertices[ indices[idx][j] ].x, ballVerts[ indices[idx][j] ].x,t );
					GLfloat y = lerp( vertices[ indices[idx][j] ].y, ballVerts[ indices[idx][j] ].y,t );
					GLfloat z = lerp( vertices[ indices[idx][j] ].z, ballVerts[ indices[idx][j] ].z,t );
					glNormal3f( nx, ny, nz );
					glVertex3f(x,y,z);
				}


				idx++;
			}
		}
		glEnd();
	}

